package org.infodavid.common.registry.impl;

import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.net.URL;
import java.util.Enumeration;
import java.util.Map;
import java.util.Properties;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * The Class PropertiesRegistry.
 * @param <K> the type of the keys
 * @param <E> the type of the elements
 */
public abstract class PropertiesRegistry<K extends Serializable,E extends Serializable> extends
    MapRegistry<K,E> {

	/** The Constant log. */
	private static final Log LOGGER = LogFactory.getLog(PropertiesRegistry.class);

	/**
	 * The Constructor.
	 * @param generator the generator
	 * @throws IOException the IO exception
	 */
	public PropertiesRegistry(final IKeyGenerator<K,E> generator) throws IOException {
		super(generator);

		initialize();
	}

	/**
	 * The Constructor.
	 * @param map the map
	 * @param generator the generator
	 * @throws IOException the IO exception
	 */
	public PropertiesRegistry(final Map<K,E> map, final IKeyGenerator<K,E> generator)
	    throws IOException {
		super(map, generator);

		initialize();
	}

	/**
	 * Gets the resource name.
	 * @return the resource name
	 */
	protected String getResourceName() {
		return getClass().getSimpleName() + ".properties";
	}

	/**
	 * Initialize.
	 * @throws IOException the IO exception
	 */
	private void initialize() throws IOException {
		final String name = getResourceName();

		if (LOGGER.isDebugEnabled()) {
			LOGGER.debug("Reading entries for properties files: " + name);
		}

		final Properties properties = new Properties();
		Enumeration<URL> resources = null;
		InputStream in = null;

		try {
			resources = getClass().getClassLoader().getResources(name);
		}
		catch (final Exception e) {
			LOGGER.debug("No properties file found", e);

			resources = null;
		}

		if (resources == null) {
			LOGGER.debug("No properties file found");
		}
		else {
			URL url;

			while (resources.hasMoreElements()) {
				url = resources.nextElement();

				if (LOGGER.isDebugEnabled()) {
					LOGGER.debug("Found descriptor: " + url);
				}

				try {
					in = url.openStream();

					if (in != null) {
						properties.load(in);
					}
				}
				finally {
					if (in != null) {
						try {
							in.close();
						}
						catch (final Exception e) {
							LOGGER.debug("An error occurs while closing input stream", e);
						}
					}
				}
			}

			register(properties);
		}
	}

	/**
	 * Register.
	 * @param properties the properties
	 */
	protected abstract void register(final Properties properties);
}
